#include <iostream>
#include <string>
#include <fstream>
#include <mpi.h>
#include "mnt.h"
#include "algo.h"
#include <stdlib.h>

using namespace std;

int static NW = 0 ;
int static N = 1 ;
int static NE = 2 ;
int static W = 3 ;
int static E = 4 ;
int static SW = 5 ;
int static S = 6 ;
int static SE = 7;

const int ETIQUETTE=1000;
const float epsylon = 0.01 ;


MNT::MNT(){

}

MNT::MNT(string nomFichier){
  // On ouvre le fichier en lecture
    ifstream fichier(nomFichier.c_str(), ios::in);


    // Si le chargement du fichier à fonctionner
    if(fichier)
    {

        float valeur ;

        string poubelle ;

        // On récupère les 6 premiere lignes du fichier
        fichier >> poubelle >> nbColonne >> poubelle >> nbLigne >> poubelle >> xllcorner >> poubelle >> yllcorner >> poubelle >> cellsize >> poubelle >> NODATA_value ;

        // On alloue de la place pour notre tableau
        creerTableau(nbLigne,nbColonne);

        for (int i = 0 ; i < nbColonne * nbLigne; i++)
        {
                fichier >> valeur ;
                // On modifie le tableau avec les valeurs récupèrées
                monTableau()[i]= valeur ;
        }

        // On ferme le fichier
        fichier.close();

    }
    else
    {

        // Erreur de lecture du fichier
        cerr << "Impossible d'ouvrir le fichier" << endl ;

    }


}

MNT::MNT(int ligne,int colonne){

    nbLigne = ligne;
    nbColonne = colonne;
    creerTableau(nbLigne,nbColonne);
}


MNT::MNT(int ligne,int colonne,float __NODATA_value,float __xllcorner,float __yllcorner,float __cellsize){

    nbLigne = ligne;
    nbColonne = colonne;
    creerTableau(nbLigne,nbColonne);
    NODATA_value = __NODATA_value;
    xllcorner = __xllcorner;
    yllcorner = __yllcorner;
    cellsize = __cellsize;
 }


// Permet de créer un tableau
void MNT::creerTableau(int ligne , int colonne)
{

    tableau = new float [colonne * ligne];


}

// Permet de modifier le nombre de ligne
void MNT::modifierLigne(int nb)
{

    nbLigne = nb ;

}

// Permet de modifier le nombre de colonne
void MNT::modifierColonne(int nb)
{

    nbColonne = nb ;

}

// Permet de modifier le data value
void MNT::modifierData(float data)
{

    NODATA_value = data ;

}

// Permet de récupèrer le nombre de ligne
int MNT::ligne()
{

    return nbLigne;
}

// Permet de récupèrer le nombre de colonne
int MNT::colonne()
{

    return nbColonne ;
}

// Permet de récupèrer le data Value
float MNT::data()
{

    return NODATA_value;
}

// Permet de récupèrer le data xllcorner
int MNT::x()
{

    return xllcorner;
}

// Permet de récupèrer le data yllcorner
int MNT::y()
{
    return yllcorner;
}

// Permet de récupèrer le data cellsize
int MNT::cell()
{
    return cellsize;
}

// Permet de récupèrer le tableau
float * MNT::monTableau()
{

    return tableau;
}


// ############# Méthode MNT ####################

// Permet d'afficher le MNT

void MNT:: afficherMNT(){

    int count = 0 ;

    for (int i = 0 ; i < nbColonne * nbLigne; i++)
    {
           count++;
           cout << tableau [i] << " ";

           if(count == nbColonne){
               count = 0;
               cout << endl ;
           }
    }

}

/**
* Permet d'écrire un mnt dans un fichier
*/
void MNT::ecrire(string nomFichier){

    // Ouverture du lecteur
    ofstream fichier(nomFichier.c_str(), ios::out | ios::trunc);


    if(fichier)
    {

            fichier <<  "ncols " << nbColonne << endl;
            fichier << "nrows " << nbLigne << endl ;

            fichier << "xllcorner "  << xllcorner << endl ;
            fichier << "yllcorner " << yllcorner << endl ;
            fichier << "cellsize " << cellsize << endl ;

            fichier << "NODATA_value " << NODATA_value << endl ;
            int count = 0 ;

            for (int i = 0 ; i < nbColonne * nbLigne; i++)
            {
                   count++;
                   fichier << tableau [i] << " ";

                   if(count == nbColonne){
                       count = 0;
                       fichier << endl ;
                   }
            }

            cout << "Write Success : " << nomFichier << endl;
            fichier.close();
    }
    else
            cerr << "Impossible d'ouvrir le fichier !" << endl;
}

/**
* Permet de calculer le maximum dans un MNT
*/
float MNT::calculMax(){

    int max = tableau[0];

    for(int i = 1 ; i < nbLigne * nbColonne ; i ++){

        if(tableau[i] > max){

            max = tableau[i];
        }
    }

    return max ;
}


/**
* Permet de remplir le tableau
*/
float * MNT::remplir(int nbLigneMNT , int pid , int nprocs, float max){

    float * W = new float[nbLigne * nbColonne];

    if( pid == 0 ) {

        // Si on est 0

        if(nbLigne == 1){

            // Si on a que une ligne
            for (int i = 0 ; i < nbColonne ; i ++){


                W[i] = tableau[i];
            }


        }else{

            //On a plus d'une ligne

            if(nbLigneMNT == 2){

                // Il y a que deux ligne dans le mnt

                // Aucune modification pour les lignes
                for (int i = 0 ; i < nbLigne * nbColonne ; i ++){

                    W[i] = tableau[i];
                }

            }else{

                // On a plus de deux lignes dans le MNT

                if(nprocs == 1){


                    // Si on a un seul proc

                    // On remplie la première ligne sans modifier
                    for (int i = 0 ; i < nbColonne ; i ++){

                        W[i] = tableau[i];
                    }

                    // On remplie la derniere ligne sans modifier
                    for (int i = ((nbLigne * nbColonne) - nbColonne) ; i < nbLigne * nbColonne ; i++ ){

                        W[i] = tableau[i];
                    }

                    // On remplie les autres en ne modifiant que le centre
                    for(int i = nbColonne ; i <  ((nbLigne * nbColonne) - nbColonne) ; i ++){

                        if( (i % nbColonne == 0) || ((i - (nbColonne -1 )) % nbColonne == 0)){


                            // On est sur un bord, pas de modification
                            W[i] = tableau[i];

                        } else {

                            // On est pas sur un bord on prérempli avec le max
                            W[i] = max ;
                        }

                    }

                }else{


                    // On a plus d'un proc

                    // On remplie la première ligne sans modifier
                    for (int i = 0 ; i < nbColonne ; i ++){

                        W[i] = tableau[i];
                    }

                    // On remplie les autres en ne modifiant que le centre
                    for(int i = nbColonne ; i <  (nbLigne * nbColonne)  ; i ++){

                        if( (i % nbColonne == 0) || ((i - (nbColonne -1 )) % nbColonne == 0)){


                            // On est sur un bord, pas de modification
                            W[i] = tableau[i];

                        } else {

                            // On est pas sur un bord on prérempli avec le max
                            W[i] = max ;
                        }

                    }

                }
            }
        }

    }else{

        // On est pas le pid 0

        if(pid == nprocs -1){

            // On est le dernier

            // On remplie la derniere ligne sans modifier
            for (int i = ((nbLigne * nbColonne ) - nbColonne) ; i < nbLigne * nbColonne ; i++ ){


                W[i] = tableau[i];
            }

            if(nbLigne > 1){

                // On remplie les autres en ne modifiant que le centre
                for(int i = 0 ; i <  ((nbLigne * nbColonne) - nbColonne) ; i ++){

                    if( (i % nbColonne == 0) || ((i - (nbColonne -1 )) % nbColonne == 0)){


                        // On est sur un bord, pas de modification
                        W[i] = tableau[i];

                    } else {

                        // On est pas sur un bord on prérempli avec le max
                        W[i] = max ;
                    }

                }
            }

        }else{

            // On est ni dernier ni 0

            // On remplie les autres en ne modifiant que le centre
            for(int i = 0 ; i <  nbLigne * nbColonne ; i ++){

                if( (i % nbColonne == 0) || ((i - (nbColonne -1 )) % nbColonne == 0)){

                    // On est sur un bord, pas de modification
                    W[i] = tableau[i];

                } else {

                    // On est pas sur un bord on prérempli avec le max
                    W[i] = max ;
                }

            }

        }
    }

    return W ;
}

/**
* Permet d'initialiser le tableau avec les valeurs au centre
*/
void MNT::initialiserTableau(float * W){

    // On initialise le tableau
    for(int i = 0 ; i < (nbLigne - 2 ) * nbColonne ; i++){

        tableau[i+nbColonne] = W[i];
    }

    for(int i = 0 ; i < nbColonne ; i++){

        tableau[i] = -1;
    }

    for(int i = 0 ; i < nbColonne ; i++ ){

        tableau[i+(((nbLigne - 2 ) * nbColonne) + nbColonne)] = -1;
    }
}

/**
* Permet d'envoyer notre ligne du dessus et notre ligne du dessous
*/
void MNT::envoi(int nprocs , int pid){


    MPI_Status statut;

    if(pid % 2 == 0){

        // Si on est un processeur pair
        // On envoi à gauche et à droite avant de recevoir

        if(pid == 0){

            // On est 0
            if(nprocs > 1){

                // On envoie notre derniere ligne à droite
                MPI_Send(&tableau[(nbLigne - 2) * nbColonne],nbColonne,MPI_FLOAT,1,ETIQUETTE,MPI_COMM_WORLD);

                // On recoit la ligne du dessous
                MPI_Recv(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
            }
        }else{

            if(pid == nprocs - 1){

                // On est le dernier on envoi que à gauche
                MPI_Send(&tableau[nbColonne],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);

                // On recoit de droite
                MPI_Recv(&tableau[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);

            }else{

                // Pour tous les autres

                // Envoie de la premiere ligne à gauche
                MPI_Send(&tableau[nbColonne],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);

                // Envoie de la derniere ligne à droite
                MPI_Send(&tableau[(nbLigne - 2) * nbColonne],nbColonne,MPI_FLOAT,pid+1,ETIQUETTE,MPI_COMM_WORLD);


                // On recoit de gauche
                MPI_Recv(&tableau[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);

                // On recoit de droite
                MPI_Recv(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
            }

        }


    }else{

        // On est un processeur impair

        if(pid == nprocs - 1){

            // Si on est le dernier
            /* Reception des lignes sur tous les procs */
            MPI_Recv(&tableau[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);


            // On est le dernier on envoi que à gauche
            MPI_Send(&tableau[nbColonne],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);

        }else{

            // Les autres

            // On recoit de gauche
            MPI_Recv(&tableau[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);

            // On recoit de droite
            MPI_Recv(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);

            // Envoie de la premiere ligne à gauche
            MPI_Send(&tableau[nbColonne],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);

            // Envoie de la derniere ligne à droite
            MPI_Send(&tableau[(nbLigne - 2) * nbColonne ],nbColonne,MPI_FLOAT,pid+1,ETIQUETTE,MPI_COMM_WORLD);

        }
    }

}

void MNT::envoiLignePartageFlux(MNT lignesPartages, int nprocs, int pid) {
	
	MPI_Status statut;
	
	
    if(pid % 2 == 0){
		
        // Si on est un processeur pair
        // On envoi à gauche et à droite avant de recevoir
		
        if(pid == 0){
			
            // On est 0
			if(nprocs > 1){
			
				// On envoie notre derniere ligne à droite
                MPI_Send(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT,1,ETIQUETTE,MPI_COMM_WORLD);
			
				// On recoit la ligne du dessous
				MPI_Recv(&lignesPartages.monTableau()[nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
			
			}	
				
        }else{
			
            if(pid == nprocs - 1){
				
                // On est le dernier on envoi que à gauche
                MPI_Send(&tableau[0],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);
				
                // On recoit de droite
                MPI_Recv(&lignesPartages.monTableau()[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
				
            }else{
				
                // Pour tous les autres
				
                // Envoie de la premiere ligne à gauche
                MPI_Send(&tableau[0],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);
				
                // Envoie de la derniere ligne à droite
                MPI_Send(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT,pid+1,ETIQUETTE,MPI_COMM_WORLD);
				
				
                // On recoit de gauche
                MPI_Recv(&lignesPartages.monTableau()[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
				
                // On recoit de droite
                MPI_Recv(&lignesPartages.monTableau()[nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
            }
			
        }
		
		
    }else{
		
        // On est un processeur impair
		
        if(pid == nprocs - 1){
			
            // Si on est le dernier
            /* Reception des lignes sur tous les procs */
            MPI_Recv(&lignesPartages.monTableau()[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
			
			
            // On est le dernier on envoi que à gauche
            MPI_Send(&tableau[0],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);
			
        }else{
			
            // Les autres
			
            // On recoit de gauche
            MPI_Recv(&lignesPartages.monTableau()[0],nbColonne,MPI_FLOAT, (pid - 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
			
            // On recoit de droite
            MPI_Recv(&lignesPartages.monTableau()[nbColonne],nbColonne,MPI_FLOAT, (pid + 1) ,ETIQUETTE,MPI_COMM_WORLD,&statut);
			
            // Envoie de la premiere ligne à gauche
            MPI_Send(&tableau[0],nbColonne,MPI_FLOAT,pid-1,ETIQUETTE,MPI_COMM_WORLD);
			
            // Envoie de la derniere ligne à droite
            MPI_Send(&tableau[(nbLigne - 1) * nbColonne],nbColonne,MPI_FLOAT,pid+1,ETIQUETTE,MPI_COMM_WORLD);
			
        }
    }
	
}



bool MNT::algorithmeRemplisage(MNT Z){

    bool condition = false ;
    float * voisins ;

    for(int i = nbColonne ; i < (nbLigne * nbColonne) - nbColonne ; i++){

        if(tableau[i] > Z.monTableau()[i - nbColonne]){


            voisins = mesVoisin(i);

            for (int n = 0 ; n < 8 ; n++){

                if(Z.monTableau()[i - nbColonne] >= (voisins[n] + epsylon)){

                    tableau[i] = Z.monTableau()[i - nbColonne] ;
                    condition = true ;

                }else{

                    if(tableau[i] > (voisins[n] + epsylon)){

                        tableau[i] = voisins[n] + epsylon ;
                        condition = true ;
                    }
                }
            }
        }
    }

    return condition ;

}


float * MNT::mesVoisin(int pos){

      float * voisin = new float[8];

      if(pos % nbColonne == 0){


          // Ligne de gauche
          voisin[NW] = -1 ;
          voisin[N] =  tableau[pos - nbColonne];
          voisin[NE] = tableau[pos -(nbColonne -1)] ;
          voisin[W] = -1 ;
          voisin[E] =  tableau[pos + 1];
          voisin[SW] = -1 ;
          voisin[S] = tableau[pos + nbColonne];
          voisin[SE] = tableau[pos + (nbColonne +1)];
      }else{

          if((pos- (nbColonne - 1)) % nbColonne == 0){

              // Ligne de droite
              voisin[NW] = tableau[pos - ( nbColonne + 1)] ;
              voisin[N] = tableau[pos - nbColonne];
              voisin[NE] = -1 ;
              voisin[W] = tableau[pos -1 ] ;
              voisin[E] =  -1;
              voisin[SW] = tableau[pos + (nbColonne -1)] ;
              voisin[S] = tableau[pos + nbColonne];
              voisin[SE] = -1;

          }else{

              // Sinon on a tous les voisins
              voisin[NW] = tableau[pos - ( nbColonne + 1)] ;
              voisin[N] =  tableau[pos - nbColonne];
              voisin[NE] = tableau[pos -(nbColonne -1)] ;
              voisin[W] = tableau[pos -1 ] ;
              voisin[E] = tableau[pos + 1];
              voisin[SW] = tableau[pos + (nbColonne -1)] ;
              voisin[S] = tableau[pos + nbColonne];
              voisin[SE] = tableau[pos + (nbColonne +1)];

          }
      }

      return voisin ;
}

int * MNT::mesVoisinIndice(int pos){
	
    int * voisin = new int[8];
	
    if(pos % nbColonne == 0){
		
		
        // Ligne de gauche
        voisin[NW] = -1 ;
        voisin[N] =  pos - nbColonne;
        voisin[NE] = pos -(nbColonne -1) ;
        voisin[W] = -1 ;
        voisin[E] =  pos + 1;
        voisin[SW] = -1 ;
        voisin[S] = pos + nbColonne;
        voisin[SE] = pos + (nbColonne +1);
    }else{
		
        if((pos- (nbColonne - 1)) % nbColonne == 0){
			
            // Ligne de droite
            voisin[NW] = pos - ( nbColonne + 1) ;
            voisin[N] =  pos - nbColonne;
            voisin[NE] = -1 ;
            voisin[W] = pos -1 ;
            voisin[E] =  -1;
            voisin[SW] = pos + (nbColonne -1) ;
            voisin[S] = pos + nbColonne;
            voisin[SE] = -1;
			
        }else{
			
            // Sinon on a tous les voisins
            voisin[NW] = pos - ( nbColonne + 1) ;
            voisin[N] =  pos - nbColonne;
            voisin[NE] = pos -(nbColonne -1) ;
            voisin[W] = pos -1 ;
            voisin[E] =  pos + 1;
            voisin[SW] = pos + (nbColonne -1) ;
            voisin[S] = pos + nbColonne;
            voisin[SE] = pos + (nbColonne +1);
			
        }
    }
	
    return voisin ;
}

void MNT::algoDirection(MNT W){

    float * voisins ;
    float min ;

    // Pour toutes les cellules
    for(int i = nbColonne ; i < (W.ligne() * nbColonne) - nbColonne ; i++){

        // Je suis mon propre min
        min = W.monTableau()[i];

        // Je récupère mes voisins
        voisins = W.mesVoisin(i);

        // Direction ecoulement sur moi même
        tableau[i - nbColonne] = 0 ;

        // Pour tous les voinsins
        for (int n = 0 ; n < 8 ; n++){

            // Si je suis plus le min
            if(min > voisins[n] && voisins[n] != -1){

                // Le voisins est le nouveau min
                min = voisins[n];

                // On met à jour la direction
                tableau[i - nbColonne] = n+1;
            }
        }
    }
}


bool MNT::testDirection(int debut , int fin){
    int * voisins ;
    int posPointeSur = -1;
    int pos ;
    int ilPointeSur ;
    int direction ;
    int i;

    for(i = debut ; i < nbColonne ; i++){

        pos = i ;
        direction = int(monTableau()[pos]);

                if(direction > 3){

                    voisins = mesVoisinIndice(pos);

                    // Je pointe sur mon voisin
                    posPointeSur = voisins[int(monTableau()[pos]-1)];

                    // On récupère les voisins de mes voisins
                    voisins = mesVoisinIndice(posPointeSur);

                    // On récupère vers qui pointe mon voisins
                    ilPointeSur = voisins[int(monTableau()[posPointeSur]-1)];

                    // Si je pointe pas sur moi même
                    if(posPointeSur !=  pos ){

                        // Si mon voisin vers qui je pointe pointe sur moi
                        if(ilPointeSur == pos){
                            cout << "direction " << int(monTableau()[pos]-1) ;
                            cout << "je pointe sur " << posPointeSur << " point sur " << ilPointeSur << " pos " << pos << " dire" << int(monTableau()[pos]-1) <<endl ;
                            return false ;
                        }

                    }


                }
    }

    // Pour se qui est au mileu
    for (int i = nbColonne ; i < fin - nbColonne ;i++){

        pos = i ;
        voisins = mesVoisinIndice(pos);

        // Je pointe sur mon voisin
        posPointeSur = voisins[int(monTableau()[pos]-1)];

        // On récupère les voisins de mes voisins
        voisins = mesVoisinIndice(posPointeSur);

        // On récupère vers qui pointe mon voisins
        ilPointeSur = voisins[int(monTableau()[posPointeSur]-1)];

        // Si je pointe pas sur moi même
        if(posPointeSur !=  pos ){

            // Si mon voisin vers qui je pointe pointe sur moi
            if(ilPointeSur == pos){
                cout << "direction " << int(monTableau()[pos]-1) ;
                cout << "je pointe sur " << posPointeSur << " point sur " << ilPointeSur << " pos " << pos << " dire" << int(monTableau()[pos]-1) <<endl ;
                return false ;
            }

        }

    }


    for(i = fin - nbColonne ; i < fin ; i++){

        pos = i ;
        direction = int(monTableau()[pos]);

                if(direction <= 3){

                    voisins = mesVoisinIndice(pos);

                    // Je pointe sur mon voisin
                    posPointeSur = voisins[int(monTableau()[pos]-1)];

                    // On récupère les voisins de mes voisins
                    voisins = mesVoisinIndice(posPointeSur);

                    // On récupère vers qui pointe mon voisins
                    ilPointeSur = voisins[int(monTableau()[posPointeSur]-1)];

                    // Si je pointe pas sur moi même
                    if(posPointeSur !=  pos ){

                        // Si mon voisin vers qui je pointe pointe sur moi
                        if(ilPointeSur == pos){
                            cout << "direction " << int(monTableau()[pos]-1) ;
                            cout << "je pointe sur " << posPointeSur << " point sur " << ilPointeSur << " pos " << pos << " dire" << int(monTableau()[pos]-1) <<endl ;
                            return false ;
                        }

                    }


                }
    }

    return true ;
}

void MNT::initialiserFlux(){
	
	for (int i=0; i< (nbLigne*nbColonne); i++) {
        tableau[i] = 1;
	}
	
	
}

void MNT::reinitialiserFluxLignesPartagees(){
	
	for (int i=0; i< (nbColonne); i++) {
		tableau[i]=1;
	}
	
	for (int i=(nbLigne-1)*nbColonne; i< (nbLigne)*nbColonne; i++) {
		tableau[i]=1;
	}
	
	
}

void MNT::algoFlux(MNT direction, MNT dejaVu, int pos){
	
	int * voisins ;
	int posPointeSur = -1;
    //int changement = false ;
	
	//On récupere la liste des voisins
	voisins = mesVoisinIndice(pos);
	
	//On récupere l'indice du voisins vers lequel on se déverse
	//On à un décalage de 1 dans notre codage des voisins par rapport à celui de la direction, donc :

    if(int(direction.monTableau()[pos]) == 0){

        posPointeSur  = pos ;

    }else{
        posPointeSur = voisins[int(direction.monTableau()[pos]-1)];
    }

    //cout << posPointeSur << " " << pos  << " " << int(direction.monTableau()[pos]) << endl;

    // Si je suis sur une ligne partagé
    if ((pos < nbColonne) || (pos > ((nbLigne-1)*nbColonne)) ) {
        changement = true;
	}
	
    // Si je ne me déverse pas sur moi même
    if (posPointeSur > -1 && pos != posPointeSur && !dejaVu.monTableau()[posPointeSur]) {
		
		// Suite de l'algo : savoir si on continue le chemin ou si on doit l'arrêter
			
        //cout << " je vais la" << endl ;
		//Si je n'ai qu'un voisin qui se déversse sur moi (celui de l'étape d'avant) ou zero (si je suis un point de départ)
		if (direction.sommeDeversemmentVoisin(pos) < 2) {
			
			
			// On donne notre flux au voisin vers lequel on se déversse
			tableau[posPointeSur] += tableau[pos];
			
			// On devient un point qui à été traité par l'algo
			dejaVu.monTableau()[pos] = true;
			
			//Et on continue l'algo avec le voisins vers lequel on se déversse
			algoFlux(direction,dejaVu,posPointeSur);
				
				
		}
			
		//Sinon, c'est que j'ai au moins 2 personnes se déverssent sur moi
		//Dans ce cas, si tous mes voisins qui se déverssent sur moi on déja été visités, je peux continuer le chemin
		else { 
			
			if (direction.continuerCheminFlux(dejaVu,pos)) {
				
				// On donne notre flux au voisin vers lequel on se déversse
				tableau[posPointeSur] += tableau[pos];
				
				// On devient un point qui à été traité par l'algo
				dejaVu.monTableau()[pos] = true;
				
				//Et on continue l'algo avec le voisins vers lequel on se déversse
				algoFlux(direction,dejaVu,posPointeSur);
					
			}
		}
	}
}

bool MNT::continuerCheminFlux(MNT dejaVu, int pos) {
	
	int * indiceVoisin;
	bool * deversementVoisin = deversementVoisins(pos);
	bool test = true;
	
	// On récupere la liste des indices des voisins de pos
	indiceVoisin = mesVoisinIndice(pos);
	
	//pour tous mes voisins
	for (int i=0; i<8; i++) {
		
		//Si mon voisin pointe sur moi
		if (deversementVoisin[i]) {
			// Si on a pas encore vu ce voisins
			if (!dejaVu.monTableau()[indiceVoisin[i]]) {
				test = false;
			}
		}
	}
	return test;
}

bool * MNT::deversementVoisins(int pos){
	
	float * voisins ;
	//On créer un tableau qui va recupérer un boolean pour tout les voisins d'un point qui indique si le voisin se déversse sur lui ou pas
	bool * deversementVoisin = new bool[8];
	
	for (int i=0; i<8; i++) {
		deversementVoisin[i] = false;
	}
	
	//On récupere la liste des voisins
	voisins = mesVoisin(pos);
	
	//pour tous mes voisins
	for (int n=0; n<8; n++) {
		
		//Si mon voisin pointe sur moi
		if (n==0) {
			if (voisins[n] == 8) {
				deversementVoisin[n] = true;
			}
		}else {
			if (n==1) {
				if (voisins[n] == 7) {
					deversementVoisin[n] = true;
				}
			}else {
				if (n==2) {
					if (voisins[n] == 6) {
						deversementVoisin[n] = true;
					}
				}else {
					if (n==3) {
						if (voisins[n] == 5) {
							deversementVoisin[n] = true;
						}
					}else {
						if (n==4) {
							if (voisins[n] == 4) {
								deversementVoisin[n] = true;
							}
						}else {
							if (n==5) {
								if (voisins[n] == 3) {
									deversementVoisin[n] = true;
								}
							}else {
								if (n==6) {
									if (voisins[n] == 2) {
										deversementVoisin[n] = true;
									}
								}else {
									if (n==7) {
										if (voisins[n] == 1) {
											deversementVoisin[n] = true;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return deversementVoisin;
}

int MNT::sommeDeversemmentVoisin(int pos) {
	
	bool * deversementVoisin;
	
	int somme = 0;
	
	deversementVoisin = deversementVoisins(pos);
	
	for (int i=0;i<8;i++){
		if (deversementVoisin[i]) somme++;
	}
	
	return somme;
	
}


void MNT::retourEcriture(int debut, int pid, int nprocs , int nbLignesParProcs , int nbLignes,int nbColonnes , string nomFichier){

    MPI_Status statut;

    // Envoyer notre nombre de ligne
    MPI_Send(&nbLignesParProcs,1,MPI_INT,0,123,MPI_COMM_WORLD);

    int lu = debut ;
    for(int i = 0 ; i < nbLignesParProcs ; i++){

        MPI_Send(&tableau[lu],nbColonnes,MPI_FLOAT,0,ETIQUETTE,MPI_COMM_WORLD);
        lu+= nbColonnes;
    }

    MNT mntEcrire(nbLignes,nbColonnes,NODATA_value,xllcorner,yllcorner,cellsize);

    int nbLigneRecu;
    int dejaRecu = 0;

    if(pid == 0){

        for (int c = 0 ; c < nprocs ; c++){

            MPI_Recv(&nbLigneRecu,1,MPI_INT,c,123,MPI_COMM_WORLD,&statut);

            for(int j = 0 ; j < nbLigneRecu ; j++){
            MPI_Recv(&mntEcrire.monTableau()[dejaRecu],nbColonnes,MPI_FLOAT,c,ETIQUETTE,MPI_COMM_WORLD,&statut);
            dejaRecu += nbColonnes;
            }

        }

        mntEcrire.ecrire(nomFichier);
    }
}
